﻿#ifndef CYUSBDEVICEMANGER_H
#define CYUSBDEVICEMANGER_H
/*
 * 此处主要负责管理所有连入当前电脑的CYUSB3014的设备
 */
#include <QWidget>
#include "CyAPI.h"
#include <windows.h>
#include <dbt.h>
#include <QVector>
#include <QDebug>
#include <utility>
#include <memory.h>
#include "CameraDataReadThread.h"

enum DeviceStatus
{
    In = 1,             // 表示设备插入
    Out = 2             // 表示设备拔出
};

// 表示一个USB设备的所有信息
struct USBDevice{
    QString m_DeviceName;       // 设备名称
    QString m_FriendlyName;     // 供用户查看的设备名称
    unsigned short m_VendorID;  // 供应商ID
    unsigned short m_ProductID; // 产品ID
    UCHAR m_InAddress;          // 输入端点地址
    UCHAR m_OutAddress;         // 输出端点地址
    UCHAR m_ControlAddress;     // 控制端地址
};

class CyUSBDeviceManger : public QWidget
{
    Q_OBJECT
public:
    explicit CyUSBDeviceManger(QWidget *parent = nullptr);

    /**
     @interpret     用于注册对应GUID的外部设备
     @param         无
     @return        无
     */
    void RegisterDeviceInterface();
    /**
     @interpret     与常规消息过滤器有点不同，nativeEvent一般处理直接由系统级别发送的信息或者事件(特别处理一些不经过qt事件循环的事件尤为有效)
     @param         eventType:表示此次事件类型，通常是一个字节数组(例如"windows_generic_msg"或其他平台特定的字符串)
     @param         message:   指向具体事件的指针，他的类型依赖于所使用的平台，在windows上通常是一个指向MSG的指针。
     @param         result:    指向长整型的指针，用于返回结果
     @return        true-成功;false-失败;
     */
    bool nativeEvent(const QByteArray &eventType, void *message, long *result) override;

    /**
     @interpret     用于返回存储USB设备的容器
     @param         无
     @return        const QVector<USBDevice>*: 返回对应地址，但是禁止修改
     */
    const QVector<USBDevice>* RUSBVectorP();

    /**
     @interpret     获取/更改当前打开的设备索引
     @param         kind: 表示获取还是更改， currentI: 获取数据时为输出型参数，否则输入数值
     @return        true-成功;false-失败;
     */
    bool CurrentOpen(ParameterKind kind, int* currentI);

    /**
     @interpret     根据提供设备名称查找对应设备索引
     @param         DeviceName: 需要打开设备的名称
     @return        该设备名称的索引(-1表示失败)
     */
    int NameToIndex(QString DeviceName);

    /**
     @interpret     根据提供设备名称查找对应设备结构
     @param         DeviceName: 需要打开设备的名称
     @return        该设备结构的句柄; nullptr表示失败;
     */
    USBDevice* NameToClass(QString DeviceName);

    /**
    @interpret     监测连入当前设备(并将连入当前计算机的设备全部加载到前端, 只能统计在程序打开前就已经连入计算机的设备，因为后面再监测就必须得new 新的CCyUSBDevice 对象
    不能使用构造函数中的CCyUSBDevice对象，并且该方法不能包含到构造函数中，因为构造函数中发送信号，上层并未connect所以得上层connect之后，再由上层调用，才能实现)
    @param         无
    @return        true-成功;false-失败;
    */
    bool CheckDeviceCon();
private:
    /**
     @interpret     对新插入的设备进行m_USBVector的数据更新（如果获取数据时currentI为-1则表示当前未打开设备）
     @param         PusbDevice: 新new的CCyUSBDevice句柄
     @return        true-成功;false-失败;
     */
    bool DeviceInsert(CCyUSBDevice* PusbDevice);
private:
    HWND m_Hwnd;                        // windows使用的窗口句柄用于后面CYUSBDevice通知当前窗口
    CCyUSBDevice* m_CyUsbDevice;        // 初始绑定m_Hwnd的结构体句柄(CCyUSBDevices只能使用new创建)
    HDEVNOTIFY*   m_HDevNotification;   // 用于注册需要关心的guid的设备
    QVector<USBDevice>  m_USBVector;    // 用于管理USB设备的信息
    int           m_CurrentOpen;        // 当前打开的设备
signals:
    void RefreshUSBDevice(DeviceStatus kind, QVector<USBDevice>* USBVector);
};

#endif // CYUSBDEVICEMANGER_H
